package com.pdh.mvc;

import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @Author: 彭_德华
 * @Date: 2021-09-15 19:38
 * 映射器（包含大量的网址与方法对应关系）
 */
public class HandlerMapping {
    private static Map<String, MVCMapping> data = new HashMap<>();

    /**
     * @param uri 请求
     * @return 对应的方法
     */
    public static MVCMapping get(String uri) {
        return data.get(uri);
    }

    /**
     * 加载配置文件，获取配置文件中的类。这个类就是来处理每个请求，执行对应的方法
     *
     * @param is
     */
    public static void load(InputStream is) {
        Properties ppt = new Properties();
        try {
            ppt.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //获取配置文件中一个个的类
        Collection<Object> values = ppt.values();
        //遍历数据 找到对应的类
        for (Object elem : values) {
            //通过反射创建一个个的对象，在获取它的方法
            String className = (String) elem;
            try {
                //加载配置文件中的每一个类
                Class c = Class.forName(className);
                //创建这个类的对象
                Object obj = c.getConstructor().newInstance();
                //获取这个类的所有方法
                Method[] methods = c.getMethods();
                for (Method m : methods) {
                    //获取这个方法上的注解
                    Annotation[] as = m.getAnnotations();
                    if (as != null) {
                        for (Annotation annotation : as) {
                            //把方法全部记录在MVCMapping里面，用于处理请求
                            if (annotation instanceof ResponseBody) {
                                //次方法用于返回字符串给客户端
                                // 把此方法存进map中
                                MVCMapping mapping = new MVCMapping(obj, m, ResponseType.TEXT);
                                Object o = data.put(((ResponseBody) annotation).value(), mapping);
                                if (o != null) {
                                    //存在重复的请求地址
                                    throw new RuntimeException("请求地址重复:" + ((ResponseBody) annotation).value());
                                }
                            } else if (annotation instanceof ResponseView) {
                                //次方法用于返回视图给客户端
                                // 把此方法存进map中
                                MVCMapping mapping = new MVCMapping(obj, m, ResponseType.VIEW);
                                Object o = data.put(((ResponseView) annotation).value(), mapping);
                                if (o != null) {
                                    //存在重复的请求地址
                                    throw new RuntimeException("请求地址重复:" + ((ResponseView) annotation).value());
                                }
                            }
                        }
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 映射对象
     *  每一个对象封装了一个方法用于处理请求
     */
    public static class MVCMapping {
        /**
         * 表示类对象（此类对象正是写到配置文件.properties里面的类）
         */
        private Object obj;

        /**
         * 方法对象
         */
        private Method method;

        /**
         * 方法的类型 TEXT/VIEW
         */
        private ResponseType type;

        public MVCMapping() {
        }

        public MVCMapping(Object obj, Method method, ResponseType type) {
            this.obj = obj;
            this.method = method;
            this.type = type;
        }

        public Object getObj() {
            return obj;
        }

        public void setObj(Object obj) {
            this.obj = obj;
        }

        public Method getMethod() {
            return method;
        }

        public void setMethod(Method method) {
            this.method = method;
        }

        public ResponseType getType() {
            return type;
        }

        public void setType(ResponseType type) {
            this.type = type;
        }
    }
}
